home *** CD-ROM | disk | FTP | other *** search
/ NetNews Offline 2 / NetNews Offline Volume 2.iso / news / comp / lang / c++-part1 / 8683 / FAQ.003
Encoding:
Internet Message Format  |  1996-08-05  |  33.8 KB

  1. Path: news1.h1.usa.pipeline.com!psinntp!psinntp!howland.reston.ans.net!newsfeed.internetmci.com!news.kei.com!newsstand.cit.cornell.edu!ub!library.erc.clarkson.edu!sun.soe.clarkson.edu!cline
  2. From: cline@sun.soe.clarkson.edu (Marshall Cline)
  3. Newsgroups: comp.lang.c++
  4. Subject: C++ FAQ: posting #3/4
  5. Followup-To: comp.lang.c++
  6. Date: 1 Feb 1996 03:20:33 GMT
  7. Organization: Paradigm Shift, Inc (technology consulting)
  8. Lines: 639
  9. Sender: cline@sun.soe.clarkson.edu
  10. Distribution: world
  11. Expires: +1 month
  12. Message-ID: <4epbi1$bpt@library.erc.clarkson.edu>
  13. Reply-To: cline@parashift.com (Marshall Cline)
  14. NNTP-Posting-Host: sun.soe.clarkson.edu
  15. Summary: Please read this before posting to comp.lang.c++
  16.  
  17. comp.lang.c++ Frequently Asked Questions list (with answers, fortunately).
  18. Copyright (C) 1991-96 Marshall P. Cline, Ph.D.
  19. Posting 3 of 4.
  20. Posting #1 explains copying permissions, (no)warranty, table-of-contents, etc
  21.  
  22. ==============================================================================
  23. SECTION 14: Style guidelines
  24. ==============================================================================
  25.  
  26. Q81: What are some good C++ coding standards?
  27.  
  28. Thank you for reading this answer rather than just trying to set your own
  29. coding standards.
  30.  
  31. But please don't ask this question on comp.lang.c++.  Nearly every software
  32. engineer has, at some point, felt that coding standards are or can be used as a
  33. "power play."  Furthermore some attempts to set C++ coding standards have been
  34. made by those unfamiliar with the language and/or paradigm, so the standards
  35. end up being based on what WAS the state-of-the-art when the standards setters
  36. where writing code.  Such impositions generate an attitude of mistrust for
  37. coding standards.
  38.  
  39. Obviously anyone who asks this question on comp.lang.c++ wants to be trained so
  40. they DON'T run off on their own ignorance, but nonetheless the answers tend to
  41. generate more heat than light.
  42.  
  43. ==============================================================================
  44.  
  45. Q82: Are coding standards necessary?  Are they sufficient?
  46.  
  47. Coding standards do not make non OO programmers into OO programmers; only
  48. training and experience do that.  If coding standards have merit, it is that
  49. they discourage the petty fragmentation that occurs when large organizations
  50. coordinate the activities of diverse groups of programmers.
  51.  
  52. But you really want more than a coding standard.  The structure provided by
  53. coding standards gives neophytes one less degree of freedom to worry about,
  54. however pragmatics go well beyond pretty-printing standards.  Organizations
  55. need a consistent PHILOSOPHY of design and implementation.  E.g., strong or
  56. weak typing?  references or ptrs in interfaces?  stream I/O or stdio?  should
  57. C++ code call our C?  vise versa?  how should ABCs be used?  should inheritance
  58. be used as an implementation technique or as a specification technique?  what
  59. testing strategy should be employed?  inspection strategy?  should interfaces
  60. uniformly have a "get" and/or "set" method for each data member?  should
  61. interfaces be designed from the outside-in or the inside-out?  should errors be
  62. handled by try/catch/throw or return codes?  etc.
  63.  
  64. What is needed is a "pseudo standard" for detailed DESIGN.  I recommend a
  65. three-pronged approach to achieving this standardization: training, mentoring,
  66. and libraries.  Training provides "intense instruction," mentoring allows OO to
  67. be caught rather than just taught, and a high quality C++ class library
  68. provides "long term instruction."  There is a thriving commercial market for
  69. all three kinds of "training."  Advice by organizations who have been through
  70. the mill is consistent: Buy, Don't Build.  Buy libraries, buy training, buy
  71. tools, buy consulting.  Companies who have attempted to become a self-taught
  72. tool-shop as well as an application/system shop have found success difficult.
  73.  
  74. Few argue that coding standards are "ideal," or even "good," however they are
  75. necessary in the kind of organizations/situations described above.
  76.  
  77. The following FAQs provide some basic guidance in conventions and styles.
  78.  
  79. ==============================================================================
  80.  
  81. Q83: Should our organization determine coding standards from our C
  82.    experience?
  83.  
  84. No!
  85.  
  86. No matter how vast your C experience, no matter how advanced your C expertise,
  87. being a good C programmer does not make you a good C++ programmer.  Converting
  88. from C to C++ is more than just learning the syntax and semantics of the "++"
  89. part of C++.  Organizations who want the promise of OOP, but who fail to put
  90. the "OO" into OOP, are fooling themselves; the balance sheet will show their
  91. folly.
  92.  
  93. C++ coding standards should be tempered by C++ experts.  Asking comp.lang.c++
  94. is a start (but don't use the term "coding standard" in the question; instead
  95. simply say, "what are the pros and cons of this technique?").  Seek out experts
  96. who can help guide you away from pitfalls.  Get training.  Buy libraries and
  97. see if "good" libraries pass your coding standards.  Do NOT set standards by
  98. yourself unless you have considerable experience in C++.  Having no standard is
  99. better than having a bad standard, since improper "official" positions "harden"
  100. bad brain traces.  There is a thriving market for both C++ training and
  101. libraries from which to pool expertise.
  102.  
  103. One more thing: whenever something is in demand, the potential for charlatans
  104. increases.  Look before you leap.  Also ask for student-reviews from past
  105. companies, since not even expertise makes someone a good communicator.
  106. Finally, select a practitioner who can teach, not a full time teacher who has a
  107. passing knowledge of the language/paradigm.
  108.  
  109. ==============================================================================
  110.  
  111. Q84: Should I declare locals in the middle of a fn or at the top?
  112.  
  113. Declare near first use.
  114.  
  115. An object is initialized (constructed) the moment it is declared.  If you don't
  116. have enough information to initialize an object until half way down the fn, you
  117. can either initialize it to an "empty" value at the top then "assign" it later,
  118. or initialize it correctly half way down the fn.  It's cheaper (in runtime
  119. performance) to get it right the first time than to build it once, tear it
  120. down, and build it again.  Simple examples show a factor of 350% speed hit for
  121. simple classes like "String".  Your mileage may vary; surely the overall system
  122. degradation will be less that 300+%, but there WILL be degradation.
  123. UNNECESSARY degradation.
  124.  
  125. A common retort to the above is: "we"ll provide "set" methods for every datum
  126. in our objects, so the cost of construction will be spread out."  This is worse
  127. than the performance overhead, since now you're introducing a maintenance
  128. nightmare.  Providing "set" methods for every datum is tantamount to public
  129. data: you've exposed your implementation technique to the world.  The only
  130. thing you've hidden is the physical NAMES of your member objects, but the fact
  131. that you're using a List and a String and a float (for example) is open for all
  132. to see.  Maintenance generally consumes far more resources than run-time CPU.
  133.  
  134. Locals should be declared near their first use.  Sorry that this isn't familiar
  135. to C experts, but "new" doesn't necessarily mean "bad."
  136.  
  137. ==============================================================================
  138.  
  139. Q85: What source-file-name convention is best? "foo.C"? "foo.cc"? "foo.cpp"?
  140.  
  141. If you already have a convention, use it.  If not, consult your compiler to see
  142. what the compiler expects.  Typical answers are: ".C", ".cc", ".cpp", or
  143. ".cxx" (naturally the ".C" extension assumes a case-sensitive file system to
  144. distinguish ".C" from ".c").
  145.  
  146. At Paradigm Shift, Inc., we use ".C" in our Makefiles even on case-insensitive
  147. file systems (on case-insensitive file systems, we supply the compiler option
  148. that means "assume all .c files are C++ source files"; e.g., "-Tdp" for IBM
  149. CSet++, "-cpp" for Zortech C++, "-P" for Borland C++, etc).
  150.  
  151. ==============================================================================
  152.  
  153. Q86: What header-file-name convention is best? "foo.H"? "foo.hh"? "foo.hpp"?
  154.  
  155. If you already have a convention, use it.  If not, and if you don't need your
  156. editor to distinguish between C and C++ files, simply use ".h".  Otherwise use
  157. whatever the editor wants, such as ".H", ".hh", or ".hpp".
  158.  
  159. At Paradigm Shift, Inc., we use ".h" for both C and C++ source files (then
  160. again, we don't create many straight C header files).
  161.  
  162. ==============================================================================
  163.  
  164. Q87: Are there any lint-like guidelines for C++?
  165.  
  166. Yes, there are some practices which are generally considered dangerous.
  167. However none of these are universally "bad," since situations arise when
  168. even the worst of these is needed:
  169.  * a class "Fred"s assignment operator should return "*this" as an "Fred&"
  170.    (allows chaining of assignments)
  171.  * a class with any virtual fns ought to have a virtual destructor
  172.  * a class with any of {destructor, assignment operator, copy constructor}
  173.    generally needs all 3
  174.  * a class "Fred"s copy constructor and assignment operator should have "const"
  175.    in the parameter: respectively "Fred::Fred(const Fred&)" and
  176.    "Fred& Fred::operator=(const Fred&)".
  177.  * always use initialization lists for class sub-objects rather than assignment
  178.    the performance difference for user-defined classes can be substantial (3x!)
  179.  * many assignment operators should start by testing if "we" are "them"; e.g.,
  180.     Fred& Fred::operator= (const Fred& fred)
  181.     {
  182.       if (this == &fred) return *this;
  183.       //...normal assignment duties...
  184.       return *this;
  185.     }
  186.    sometimes there is no need to check, but these situations generally
  187.    correspond to when there's no need for an explicit user-specified assignment
  188.    op (as opposed to a compiler-synthesized assignment-op).
  189.  * in classes that define both "+=," "+" and "=," "a+=b" and "a=a+b" should
  190.    generally do the same thing; ditto for the other identities of builtin types
  191.    (e.g., a+=1 and ++a; p[i] and *(p+i); etc).  This can be enforced by writing
  192.    the binary ops using the "op=" forms; e.g.,
  193.     Fred operator+ (const Fred& a, const Fred& b)
  194.     {
  195.       Fred ans = a;
  196.       ans += b;
  197.       return ans;
  198.     }
  199.    This way the "constructive" binary ops don't even need to be friends.  But
  200.    it is sometimes possible to more efficiently implement common ops (e.g., if
  201.    class "Fred" is actually "String," and "+=" has to reallocate/copy string
  202.    memory, it may be better to know the eventual length from the beginning).
  203.  
  204. ==============================================================================
  205. SECTION 15: Keys for Smalltalk programmers to learn C++
  206. ==============================================================================
  207.  
  208. Q88: Why does C++'s FAQ have a section on Smalltalk? Is this
  209.    Smalltalk-bashing?
  210.  
  211. The two "major" OOPLs in the world are C++ and Smalltalk.  Due to its
  212. popularity as the OOPL with the second largest user pool, many new C++
  213. programmers come from a Smalltalk background.  This section answers the
  214. questions:
  215.  * what's different about the two languages
  216.  * what must a Smalltalk-turned-C++ programmer know to master C++
  217.  
  218. This section does *!*NOT*!* attempt to answer the questions:
  219.  * which language is "better"?
  220.  * why is Smalltalk "bad"?
  221.  * why is C++ "bad"?
  222.  
  223. Nor is it an open invitation for some Smalltalk terrorist to slash my tires
  224. while I sleep (on those rare occasions when I have time to rest these days :-).
  225.  
  226. ==============================================================================
  227.  
  228. Q89: What's the difference between C++ and Smalltalk?
  229.  
  230. The most important differences are:
  231.  
  232.  * static typing vs dynamic typing?
  233.  * must inheritance be used for subtyping only?
  234.  * value vs reference semantics?
  235.  
  236. The first two differences are illuminated in the remainder of this section; the
  237. third point is the subject of the section that follows.
  238.  
  239. If you're a Smalltalk programmer who wants to learn C++, you'd be very wise to
  240. study the next three FAQs carefully.
  241.  
  242. ==============================================================================
  243.  
  244. Q90: What is "static typing", and how is it similar/dissimilar to Smalltalk?
  245.  
  246. Static typing says the compiler checks the type-safety of every operation
  247. STATICALLY (at compile-time), rather than to generate code which will check
  248. things at run-time.  For example, with static typing, the signature matching of
  249. fn arguments is checked, and an improper match is flagged as an error by the
  250. COMPILER, not at run-time.
  251.  
  252. In OO code, the most common "typing mismatch" is invoking a member function
  253. against an object which isn't prepared to handle the operation.  E.g., if class
  254. "Fred" has member fn "f()" but not "g()", and "fred" is an instance of class
  255. "Fred", then "fred.f()" is legal and "fred.g()" is illegal.  C++ (statically
  256. typed) catches the error at compile time, and Smalltalk (dynamically typed)
  257. catches the error at run-time.  (Technically speaking, C++ is like Pascal
  258. --PSEUDO statically typed-- since ptr casts and unions can be used to violate
  259. the typing system; which reminds me: only use ptr casts and unions as often as
  260. you use "goto"s).
  261.  
  262. ==============================================================================
  263.  
  264. Q91: Which is a better fit for C++: "static typing" or "dynamic typing"?
  265.  
  266. If you want to use C++ most effectively, use it as a statically typed language.
  267.  
  268. C++ is flexible enough that you can (via ptr casts, unions, and #defines) make
  269. it "look" like Smalltalk.  But don't.  Which reminds me: try to avoid #define.
  270.  
  271. There are places where ptr casts and unions are necessary and even wholesome,
  272. but they should be used carefully and sparingly.  A ptr cast tells the compiler
  273. to believe you.  An incorrect ptr cast might corrupt your heap, scribble into
  274. memory owned by other objects, call nonexistent methods, and cause general
  275. failures.  It's not a pretty sight.  If you avoid these and related constructs,
  276. you can make your C++ code both safer and faster, since anything that can be
  277. checked at compile time is something that doesn't have to be done at run-time.
  278.  
  279. Even if you're in love with dynamic typing, please avoid it in C++, or else
  280. please consider using another language that better supports your desire to
  281. defer typing decisions to run-time.  C++ performs 100% of its type checking at
  282. compile time; it has NO built-in mechanism to do ANY type checking at run-time.
  283. If you use C++ as a dynamically typed OOPL, your life is in your own hands.
  284.  
  285. ==============================================================================
  286.  
  287. Q92: How can you tell if you have a dynamically typed C++ class library?
  288.  
  289. Hint #1: when everything is derived from a single root class, usually "Object."
  290. Hint #2: when the container classes (List, Stack, Set, etc) are non-templates.
  291. Hint #3: when the container classes (List, Stack, Set, etc) insert/extract
  292. elements as pointers to "Object" (you can put an Apple into such a container,
  293. but when you get it out, the compiler knows only that it is derived from
  294. Object, so you have to use a pointer cast to convert it back to an Apple*; and
  295. you better pray a lot that it really IS an Apple, cause your blood is on your
  296. own head).
  297.  
  298. You can make the pointer cast "safe" by using "dynamic_cast" (added to the
  299. language in 1994), but this dynamic testing is just that: dynamic.  This
  300. coding style is the essence of dynamic typing in C++.  You call a function
  301. that says "convert this Object into an Apple or give me NULL if its not an
  302. Apple," and you've got dynamic typing: you don't know what will happen until
  303. run-time.
  304.  
  305. When you use with templates to implement your containers, the C++ compiler can
  306. statically validate 99% of an application's typing information (the figure
  307. "99%" is apocryphal; some claim they always get 100%, those who need
  308. persistence get something less than 100% static type checking).  The point is:
  309. C++ gets genericity from templates, not from inheritance.
  310.  
  311. ==============================================================================
  312.  
  313. Q93: How do you use inheritance in C++, and is that different from Smalltalk?
  314.  
  315. Some people believe that the purpose of inheritance is code reuse.  In C++,
  316. this is wrong.  Stated plainly, "inheritance is not 'for' code reuse."
  317.  
  318. The purpose of inheritance in C++ is to express interface compliance
  319. (subtyping), not to get code reuse.  In C++, code reuse usually comes via
  320. composition rather than via inheritance.  In other words, inheritance is mainly
  321. a specification technique rather than an implementation technique.
  322.  
  323. This is a major difference with Smalltalk, where there is only one form of
  324. inheritance (C++ provides "private" inheritance to mean "share the code but
  325. don't conform to the interface", and "public" inheritance to mean "kind-of").
  326. The Smalltalk language proper (as opposed to coding practice) allows you to
  327. have the EFFECT of "hiding" an inherited method by providing an override that
  328. calls the "does not understand" method.  Furthermore Smalltalk allows a
  329. conceptual "is-a" relationship to exist APART from the subclassing hierarchy
  330. (subtypes don't have to be subclasses; e.g., you can make something that is-a
  331. Stack yet doesn't inherit from class Stack).
  332.  
  333. In contrast, C++ is more restrictive about inheritance: there's no way to make
  334. a "conceptual is-a" relationship without using inheritance (the C++ work-around
  335. is to separate interface from implementation via ABCs).  The C++ compiler
  336. exploits the added semantic information associated with public inheritance to
  337. provide static typing.
  338.  
  339. ==============================================================================
  340.  
  341. Q94: What are the practical consequences of diffs in Smalltalk/C++
  342.    inheritance?
  343.  
  344. Smalltalk lets you make a subtype that isn't a subclass, and allows you to make
  345. a subclass that isn't a subtype.  This allows Smalltalk programmers to be very
  346. carefree in putting data (bits, representation, data structure) into a class
  347. (e.g., you might put a linked list into a Stack class).  After all, if someone
  348. wants an array-based-Stack, they don't have to inherit from Stack; they could
  349. inherit such a class from Array if desired, even though an ArrayBasedStack is
  350. NOT a kind-of Array!
  351.  
  352. In C++, you can't be nearly as carefree.  Only mechanism (method code), but not
  353. representation (data bits) can be overridden in subclasses.  Therefore you're
  354. usually better off NOT putting the data structure in a class.  This leads to a
  355. stronger reliance on Abstract Base Classes (ABCs).
  356.  
  357. I like to think of the difference between an ATV and a Maseratti.  An ATV (all
  358. terrain vehicle) is more fun, since you can "play around" by driving through
  359. fields, streams, sidewalks, and the like.  A Maseratti, on the other hand, gets
  360. you there faster, but it forces you to stay on the road.  My advice to C++
  361. programmers is simple: stay on the road.  Even if you're one of those people
  362. who like the "expressive freedom" to drive through the bushes, don't do it in
  363. C++; it's not a good fit.
  364.  
  365. ==============================================================================
  366.  
  367. Q95: Do you need to learn a "pure" OOPL before you learn C++?
  368.  
  369. No (in fact, doing so might actually hurt you).
  370.  
  371. (Note that Smalltalk is a "pure" OOPL, and C++ is a "hybrid" OOPL).  Before
  372. reading this, please read the previous FAQs on the difference between C++ and
  373. Smalltalk.
  374.  
  375. The "purity" of the OOPL doesn't make the transition to C++ any easier.  In
  376. fact, the typical use of dynamic typing and non-subtyping inheritance can make
  377. it even harder for Smalltalk programmers to learn C++.  Paradigm Shift, Inc.,
  378. has taught OO technology to literally thousands of people, and we have noticed
  379. that people who want to learn C++ from a Smalltalk background usually have just
  380. as hard a time as those who've never seen inheritance before.  In fact, those
  381. with extensive experience with a dynamically typed OOPL (usually but not always
  382. Smalltalk) might even have a HARDER time, since it's harder to UNLEARN habits
  383. than it is to learn the statically typed way from the beginning.
  384.  
  385. ==============================================================================
  386.  
  387. Q96: What is the NIHCL?  Where can I get it?
  388.  
  389. NIHCL stands for "national-institute-of-health's-class-library."
  390. it can be acquired via anonymous ftp from [128.231.128.7]
  391. in the file pub/NIHCL/nihcl-3.0.tar.Z
  392.  
  393. NIHCL (some people pronounce it "N-I-H-C-L," others pronounce it like "nickel")
  394. is a C++ translation of the Smalltalk class library.  There are some ways where
  395. NIHCL's use of dynamic typing helps (e.g., persistent objects).  There are also
  396. places where its use of dynamic typing creates tension with the static typing
  397. of the C++ language.
  398.  
  399. See previous FAQs on Smalltalk for more.
  400.  
  401. ==============================================================================
  402. SECTION 16: Reference and value semantics
  403. ==============================================================================
  404.  
  405. Q97: What is value and/or reference semantics, and which is best in C++?
  406.  
  407. With reference semantics, assignment is a pointer-copy (i.e., a REFERENCE).
  408. Value (or "copy") semantics mean assignment copies the value, not just the
  409. pointer.  C++ gives you the choice: use the assignment operator to copy the
  410. value (copy/value semantics), or use a ptr-copy to copy a pointer (reference
  411. semantics).  C++ allows you to override the assignment operator to do anything
  412. your heart desires, however the default (and most common) choice is to copy the
  413. VALUE.
  414.  
  415. Pros of reference semantics: flexibility and dynamic binding (you get dynamic
  416. binding in C++ only when you pass by ptr or pass by ref, not when you pass by
  417. value).
  418.  
  419. Pros of value semantics: speed.  "Speed" seems like an odd benefit to for a
  420. feature that requires an object (vs a ptr) to be copied, but the fact of the
  421. matter is that one usually accesses an object more than one copies the object,
  422. so the cost of the occasional copies is (usually) more than offset by the
  423. benefit of having an actual object rather than a ptr to an object.
  424.  
  425. There are three cases when you have an actual object as opposed to a pointer to
  426. an object: local vars, global/static vars, and fully contained member objects
  427. in a class.  The most important of these is the last ("composition").
  428.  
  429. More info about copy-vs-reference semantics is given in the next FAQs.  Please
  430. read them all to get a balanced perspective.  The first few have intentionally
  431. been slanted toward value semantics, so if you only read the first few of the
  432. following FAQs, you'll get a warped perspective.
  433.  
  434. Assignment has other issues (e.g., shallow vs deep copy) which are not covered
  435. here.
  436.  
  437. ==============================================================================
  438.  
  439. Q98: What is "virtual data," and how-can / why-would I use it in C++?
  440.  
  441. Virtual data allows a derived class to change the exact class of a base class's
  442. member object.  Virtual data isn't strictly "supported" by C++, however it
  443. can be simulated in C++.  It ain't pretty, but it works.
  444.  
  445. To simulate virtual data in C++, the base class must have a pointer to the
  446. member object, and the derived class must provide a "new" object to be pointed
  447. to by the base class's pointer.  The base class would also have one or more
  448. normal constructors that provide their own referrent (again via "new"), and the
  449. base class's destructor would "delete" the referent.
  450.  
  451. For example, class "Stack" might have an Array member object (using a pointer),
  452. and derived class "StretchableStack" might override the base class member data
  453. from "Array" to "StretchableArray".  For this to work, StretchableArray would
  454. have to inherit from Array, so Stack would have an "Array*".  Stack's normal
  455. constructors would initialize this "Array*" with a "new Array", but Stack would
  456. also have a (possibly "protected:") constructor that would accept an "Array*"
  457. from a derived class.  StretchableArray's constructor would provide a "new
  458. StretchableArray" to this special constructor.
  459.  
  460. Pros:
  461.  * Easier implementation of StretchableStack (most of the code is inherited).
  462.  * Users can pass a StretchableStack as a kind-of Stack.
  463.  
  464. Cons:
  465.  * Adds an extra layer of indirection to access the Array.
  466.  * Adds some extra freestore allocation overhead (both new and delete).
  467.  * Adds some extra dynamic binding overhead (reason given in next FAQ).
  468.  
  469. In other words, we succeeded at making OUR job easier as the implementor of
  470. StretchableStack, but all our users pay for it.  Unfortunately the extra
  471. overhead was imposed on both users of StretchableStack AND on users of Stack.
  472.  
  473. See the FAQ after the next to find out how much the users "pay."  Also: PLEASE
  474. read the few FAQs that follow the next one too (YOU WILL NOT GET A BALANCED
  475. PERSPECTIVE WITHOUT THE OTHERS).
  476.  
  477. ==============================================================================
  478.  
  479. Q99: What's the difference between virtual data and dynamic data?
  480.  
  481. The easiest way to see the distinction is by an analogy with "virtual fns":
  482. A virtual member fn means the declaration (signature) must stay the same in
  483. subclasses, but the defn (body) can be overridden.  The overriddenness of an
  484. inherited member fn is a static property of the subclass; it doesn't change
  485. dynamically throughout the life of any particular object, nor is it possible
  486. for distinct objects of the subclass to have distinct defns of the member fn.
  487.  
  488. Now go back and re-read the previous paragraph, but make these substitutions:
  489.  * "member fn" --> "member object"
  490.  * "signature" --> "type"
  491.  * "body"      --> "exact class'
  492. After this, you'll have a working definition of virtual data.
  493.  
  494. Another way to look at this is to distinguish "per-object" member functions
  495. from "dynamic" member functions.  A "per-object" member fn is a member fn that
  496. is potentially different in any given instance of an object, and could be
  497. implemented by burying a function ptr in the object; this pointer could be
  498. "const", since the pointer will never be changed throughout the object's life.
  499. A "dynamic" member fn is a member fn that will change dynamically over time;
  500. this could also be implemented by a function ptr, but the fn ptr would not be
  501. const.
  502.  
  503. Extending the analogy, this gives us three distinct concepts for data members:
  504.  * virtual data: the defn ("class") of the member object is overridable in
  505.    subclasses provided its declaration ("type") remains the same, and this
  506.    overriddenness is a static property of the subclass.
  507.  * per-object-data: any given object of a class can instantiate a different
  508.    conformal (same type) member object upon initialization (usually a "wrapper"
  509.    object), and the exact class of the member object is a static property of
  510.    the object that wraps it.
  511.  * dynamic-data: the member object's exact class can change dynamically over
  512.    time.
  513.  
  514. The reason they all look so much the same is that none of this is "supported"
  515. in C++.  It's all merely "allowed," and in this case, the mechanism for faking
  516. each of these is the same: a ptr to a (probably abstract) base class.  In a
  517. language that made these "first class" abstraction mechanisms, the difference
  518. would be more striking, since they'd each have a different syntactic variant.
  519.  
  520. ==============================================================================
  521.  
  522. Q100: Should I normally use pointers to freestore allocated objects for my
  523.    data members, or should I use "composition"?
  524.  
  525. Composition.
  526.  
  527. Your member objects should normally be "contained" in the composite object (but
  528. not always; "wrapper" objects are a good example of where you want a ptr/ref;
  529. also the N-to-1-uses-a relationship needs something like a ptr/ref).
  530.  
  531. There are three reasons why fully contained member objects ("composition") has
  532. better performance than ptrs to freestore-allocated member objects:
  533.  
  534.  * Extra layer to indirection every time you need to access the member object.
  535.  * Extra freestore allocations ("new" in constructor, "delete" in destructor).
  536.  * Extra dynamic binding (reason given below).
  537.  
  538. ==============================================================================
  539.  
  540. Q101: What are relative costs of the 3 performance hits associated with
  541.    allocating member objects from the freestore?
  542.  
  543. The three performance hits are enumerated in the previous FAQ:
  544.  * By itself, an extra layer of indirection is small potatoes.
  545.  * Freestore allocations can be a performance issue (the performance of the
  546.    typical implementation of malloc degrades when there are many allocations;
  547.    OO s/w can easily become "freestore bound" unless you're careful).
  548.  * The extra dynamic binding comes from having a ptr rather than an object.
  549.    Whenever the C++ compiler can know an object's EXACT class, virtual fn
  550.    calls can be STATICALLY bound, which allows inlining.  Inlining allows
  551.    zillions (would you believe half a dozen :-) optimization opportunities
  552.    such as procedural integration, register lifetime issues, etc.  The C++
  553.    compiler can know an object's exact class in three circumstances: local
  554.    variables, global/static variables, and fully-contained member objects.
  555.  
  556. Thus fully-contained member objects allow significant optimizations that
  557. wouldn't be possible under the "member objects-by-ptr" approach.  This is the
  558. main reason that languages which enforce reference-semantics have "inherent"
  559. performance challenges.
  560.  
  561. NOTE: PLEASE READ THE NEXT THREE FAQs TO GET A BALANCED PERSPECTIVE!
  562.  
  563. ==============================================================================
  564.  
  565. Q102: Are "inline virtual" member fns ever actually "inlined"?
  566.  
  567. Yes but...
  568.  
  569. A virtual call via a ptr or ref is always resolved dynamically, which can never
  570. be inlined.  Reason: the compiler can't know which actual code to call until
  571. run-time (i.e., dynamically), since the code may be from a derived class that
  572. was created after the caller was compiled.
  573.  
  574. Therefore the only time an inline virtual call can be inlined is when the
  575. compiler knows the "exact class" of the object which is the target of the
  576. virtual function call.  This can happen only when the compiler has an actual
  577. object rather than a pointer or reference to an object.  I.e., either with a
  578. local object, a global/static object, or a fully contained object inside a
  579. composite.
  580.  
  581. Note that the difference between inlining and non-inlining is normally MUCH
  582. more significant than the difference between a regular fn call and a virtual fn
  583. call.  For example, the difference between a regular fn call and a virtual fn
  584. call is often just two extra memory references, but the difference between an
  585. inline function and a non-inline function can be as much as an order of
  586. magnitude (for zillions of calls to insignificant member fns, loss of inlining
  587. virtual fns can result in 25X speed degradation!  [Doug Lea, "Customization in
  588. C++," proc Usenix C++ 1990]).
  589.  
  590. A practical consequence of this insight: don't get bogged down in the endless
  591. debates (or sales tactics!) of compiler/language vendors who compare the cost
  592. of a virtual function call on their language/compiler with the same on another
  593. language/compiler.  Such comparisons are largely meaningless when compared with
  594. the ability of the language/compiler to "inline expand" member function calls.
  595. I.e., many language implementation vendors make a big stink about how good
  596. their dispatch strategy is, but if these implementations don't INLINE method
  597. calls, the overall system performance would be poor, since it is inlining --NOT
  598. dispatching-- that has the greatest performance impact.
  599.  
  600. NOTE: PLEASE READ THE NEXT TWO FAQs TO SEE THE OTHER SIDE OF THIS COIN!
  601.  
  602. ==============================================================================
  603.  
  604. Q103: Sounds like I should never use reference semantics, right?
  605.  
  606. Wrong.
  607.  
  608. Reference semantics are A Good Thing.  We can't live without pointers.  We just
  609. don't want our s/w to be One Gigantic Rats Nest Of Pointers.  In C++, you can
  610. pick and choose where you want reference semantics (ptrs/refs) and where you'd
  611. like value semantics (where objects physically contain other objects etc).  In
  612. a large system, there should be a balance.  However if you implement absolutely
  613. EVERYTHING as a pointer, you'll get enormous speed hits.
  614.  
  615. Objects near the problem skin are larger than higher level objects.  The
  616. IDENTITY of these "problem space" abstractions is usually more important than
  617. their "value."  Thus reference semantics should be used for problem-space
  618. objects.
  619.  
  620. Note that these problem space objects are normally at a higher level of
  621. abstraction than the solution space objects, so the problem space objects
  622. normally have a relatively lower frequency of interaction.  Therefore C++ gives
  623. us an IDEAL situation: we choose reference semantics for objects that need
  624. unique identity or that are too large to copy, and we can choose value
  625. semantics for the others.  Thus the highest frequency objects will end up with
  626. value semantics, since we install flexibility where it doesn't hurt us (only),
  627. and we install performance where we need it most!
  628.  
  629. These are some of the many issues the come into play with real OO design.
  630. OO/C++ mastery takes time and high quality training.  If you want a powerful
  631. tool, you've got to invest.
  632.  
  633.            <<<<DON'T STOP NOW!  READ THE NEXT FAQ TOO!!>>>>
  634.  
  635. ==============================================================================
  636.  
  637. Q104: Does the poor performance of ref semantics mean I should pass-by-value?
  638.  
  639. Nope.
  640.  
  641. The previous FAQ were talking about MEMBER OBJECTS, not parameters.  Generally,
  642. objects that are part of an inheritance hierarchy should be passed by ref or by
  643. ptr, NOT by value, since only then do you get the (desired) dynamic binding
  644. (pass-by-value doesn't mix with inheritance, since larger subclass objects get
  645. "sliced" when passed by value as a base class object).
  646.  
  647. Unless compelling reasons are given to the contrary, member objects should be
  648. by value and parameters should be by reference.  The discussion in the previous
  649. few FAQs indicates some of the "compelling reasons" for when member objects
  650. should be by reference.
  651.  
  652. --
  653. Paradigm Shift, Inc. / P.O. Box 5108 / Potsdam, NY  13676
  654. Technology consulting services
  655. cline@parashift.com / Voice: 315-353-6100 / FAX: 315-353-6110
  656.